#include "lm3s2965.h"
#include "hw_ints.h"
#include "hw_memmap.h"
#include "hw_types.h"
#include "debug.h"
#include "gpio.h"
#include "interrupt.h"
#include "sysctl.h"
#include "uart.h"
#include "rit128x96x4.h"
#include "systick.h"
#include "MR102A.h"
#include <stdlib.h>
#include <stdio.h>
#include "timer.h"

//#Defines
#define US_PER_SEC 1000000
#define TICKS_PER_US 6
#define STX 0x02
#define MSB 0x00
#define LSB txMessageLength+7
#define COMADR 0xFF
#define CRC_POLYNOM 0x8408
#define MAX_MESSAGE_LENGTH 64
#define RFID_BASE UART1_BASE

//Module level variables
static char * message_TX;
static char message_RX[128];
static char txMessageLength;
static char rxMessageLength;
static char newMessageReady;
static char scanMode=1;
static char tagStatus[3];
static char timeOut=0;
static int messageIndex=0;

void initComm(void);
void transmit(void);
void receiveResponse(void);
unsigned int CRC16();

// Initializes UART for MR102A communication and configures reader
void MR102AInit(void)
{	
	message_TX=(char*)malloc(MAX_MESSAGE_LENGTH*sizeof(char));//Allocates bytes for a tx message
	// enable peripherals
	SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);

	// Set up a Timer
	TimerConfigure(TIMER0_BASE,TIMER_CFG_32_BIT_OS);
	TimerIntEnable(TIMER0_BASE,TIMER_TIMA_TIMEOUT);
	IntEnable(INT_TIMER0A);

	// Set GPIO D2 and D3 as UART pins.
	GPIOPinTypeUART(GPIO_PORTD_BASE, GPIO_PIN_2 | GPIO_PIN_3);

	// configure UART protocol
	UARTConfigSetExpClk(RFID_BASE, 8000000,9600,UART_CONFIG_WLEN_8|UART_CONFIG_STOP_ONE |UART_CONFIG_PAR_EVEN);	// 38400 baud, 8 data bits, even parity, one stop bit

	// Enable RX FIFO, trigger the interrupt when 2 bytes are in the fifo
	UARTFIFOEnable(RFID_BASE);
	UARTFIFOLevelSet(RFID_BASE,UART_FIFO_TX2_8,UART_FIFO_RX1_8);

	// enable interrupts
	IntEnable(INT_UART1);
	UARTIntEnable(RFID_BASE, UART_INT_RX);    // | UART_INT_RT);

	// enable processor interrupts (yeah...)
	IntMasterEnable();

	// enable UART
	UARTEnable(RFID_BASE);

	//Set up configuration of MR102A.  Uncomment if the reader is not behaving properly.  These settings should be default now, however.
}

void tagEventChecker(int returnArr[])
{
	static char oldTagStatus=0;
	char buffer[50];

	//returnArr[0] = -1;

	if(tagStatus[0]!=oldTagStatus)
	{
		if(tagStatus[0]==1)
		{
			printf("Tag %i was seen\n",tagStatus[1]);
			printf("Event Angle: %i\n",tagStatus[2]);
			//Post event tag found with event parameter event angle
			returnArr[0] = TAG_FOUND;
			returnArr[1] = tagStatus[1];	//tag id
		}
		else
		{
			printf(buffer, "Tag %i was lost\n",tagStatus[1]);
			printf(buffer, "Event Angle: %i\n",tagStatus[2]);
			//Post event tag lost with event parameter event angle
			returnArr[0] = TAG_LOST;
			returnArr[1] = tagStatus[1];	//tag id
		}
		oldTagStatus=tagStatus[0];
	}
}

void transmit()
{
	int i;
	int j;
	message_TX[txMessageLength+5]=(char)(CRC16()&0xFF);
	message_TX[txMessageLength+6]=(char)((CRC16()>>8)&0xFF);
	for(i=0;i<txMessageLength+7;i++)
	{
		while(1)
		{
			if(~UARTBusy(RFID_BASE))
			{
				UARTCharPutNonBlocking(RFID_BASE,message_TX[i]);
				break;
			}
		}
		//Waste some time
		for(j=0;j<1000;j++)
		{
			j++;
			j--;
		}
	}
}

//This is the receive function for messages sent from the reader via the scan protocol
void receiveScan()
{
	unsigned int timeLeft;
	while(UARTCharsAvail(RFID_BASE))
	{
		message_RX[messageIndex]=UARTCharGet(RFID_BASE);
		timeLeft=TimerValueGet(TIMER0_BASE,TIMER_A);
		if(messageIndex==16)
		{
			messageIndex=0;
			tagStatus[0]=1;//The tag is visible
			tagStatus[1]=(message_RX[13]+message_RX[14]+message_RX[15]);//The name of the tag
			//tagFound[2]=Angle at which that tag was first seen
			//If you don't see that tag again in 300ms, you've lost it
			TimerLoadSet(TIMER0_BASE,TIMER_A,6000000);
			TimerEnable(TIMER0_BASE,TIMER_A);
			/*while(UARTCharsAvail(RFID_BASE))
			{
				//Get rid of any more stupid characters
				message_RX[17]=UARTCharGet(RFID_BASE);
			}*/
		}
		else
		{
			messageIndex++;
		}
		timeLeft=TimerValueGet(TIMER0_BASE,TIMER_A);
	}
}

//This is the receive function for responses to commands sent to the reader
void receiveResponse()
{
	static int messageIndex=0;
	while(UARTCharsAvail(RFID_BASE))
	{
		message_RX[messageIndex]=UARTCharGet(RFID_BASE);
		if(messageIndex==2)
		{
			rxMessageLength=message_RX[2];
		}
		if(messageIndex==rxMessageLength-1)
		{
			newMessageReady=1;
			messageIndex=0;
		}
		else
			messageIndex++;
	}
}

unsigned int CRC16()
{
	unsigned int crc=0xFFFF;
	char cnt=txMessageLength+5;// cnt = number of protocol bytes without CRC
	int i;
	int j;
	for (i = 0; i < cnt; i++)
	{
		crc ^= message_TX[i];
		for (j = 0; j < 8; j++)
		{
			if (crc & 0x0001)
				crc = (crc >> 1) ^ CRC_POLYNOM;
			else
				crc = (crc >> 1);
		}
	}
	return crc;
}

void waitForResponseBlocking(char controlByte)
{
	char message4;
	char message5;
	while(1)
	{

		if(newMessageReady==1)
		{
			message4=message_RX[4];
			message5=message_RX[5];
			newMessageReady=0;
			if((message_RX[4]==controlByte)&&(message_RX[5]==0x00))
			{
				break;
			}
		}else
		{
			receiveResponse();
		}
	}
}

void resetMR102A(void)
{
	char buffer[50];
	scanMode=0;
	//This first message confirms the baud rate (should be 9600, as set in UART Configuation
	txMessageLength=1;
	message_TX[0]=STX;
	message_TX[1]=MSB;
	message_TX[2]=LSB;
	message_TX[3]=COMADR;
	message_TX[4]=0x52;
	message_TX[5]=0x00;
	//Send that message
	transmit();
	//Wait for a response, and check if action was successful
	waitForResponseBlocking(0x52);
	//This message logs the host into the reader with password 0x00(x3) so that the host has permission to change CFG parameters
	txMessageLength=4;
	message_TX[0]=STX;
	message_TX[1]=MSB;
	message_TX[2]=LSB;
	message_TX[3]=COMADR;
	message_TX[4]=0xA0;
	message_TX[5]=0x00;
	message_TX[6]=0x00;
	message_TX[7]=0x00;
	message_TX[8]=0x00;
	//Send that message
	transmit();
	//Wait for a response, and check if action was successful
	waitForResponseBlocking(0xA0);
	//This message writes configuration parameters to CFG1.  This includes setting the baud rate and putting us in scan mode
	txMessageLength=15;
	message_TX[0]=STX;
	message_TX[1]=MSB;
	message_TX[2]=LSB;
	message_TX[3]=COMADR;
	message_TX[4]=0x81;
	message_TX[5]=0x81;
	message_TX[6]=0x00;
	message_TX[7]=0x00;
	message_TX[8]=0x06;
	message_TX[9]=0x01;
	message_TX[10]=0x00;
	message_TX[11]=0x00;
	message_TX[12]=0x01;
	message_TX[13]=0x2C;
	message_TX[14]=0x00;
	message_TX[15]=0x00;
	message_TX[16]=0x00;
	message_TX[17]=0x00;
	message_TX[18]=0x80;
	message_TX[19]=0x01;
	//Send that message
	transmit();
	//Wait for a response, and check if action was successful
	waitForResponseBlocking(0x81);
	//This message writes to the CFG12 Register, including setting the read-again time to 200ms
	txMessageLength=15;
	message_TX[0]=STX;
	message_TX[1]=MSB;
	message_TX[2]=LSB;
	message_TX[3]=COMADR;
	message_TX[4]=0x81;
	message_TX[5]=0x8C;//Also writes to EEPROM!
	message_TX[6]=0x00;//MSB of Valid Time
	message_TX[7]=0x00;//LSB of Valid Time
	message_TX[8]=0x01;
	message_TX[9]=0x00;
	message_TX[10]=0x01;
	message_TX[11]=0x00;
	message_TX[12]=0x00;
	message_TX[13]=0x00;
	message_TX[14]=0x00;
	message_TX[15]=0x00;
	message_TX[16]=0x00;
	message_TX[17]=0x00;
	message_TX[18]=0x00;
	message_TX[19]=0x00;
	//Send that message
	transmit();
	//Wait for a response, and check if action was successful
	waitForResponseBlocking(0x81);
	//This message writes to CFG13, which controls lots of scan mode protocol parameters
	txMessageLength=15;
	message_TX[0]=STX;
	message_TX[1]=MSB;
	message_TX[2]=LSB;
	message_TX[3]=COMADR;
	message_TX[4]=0x81;
	message_TX[5]=0x8D;
	message_TX[6]=0x02;
	message_TX[7]=0x80;//SepChar
	message_TX[8]=0x00;
	message_TX[9]=0x02;//
	message_TX[10]=0xAA;//One User-defined ENDCHAR, AA
	message_TX[11]=0xAA;
	message_TX[12]=0xAA;
	message_TX[13]=0x00;
	message_TX[14]=0x0F;
	message_TX[15]=0x0F;
	message_TX[16]=0x0F;
	message_TX[17]=0x00;
	message_TX[18]=0x00;
	message_TX[19]=0x00;//One user defined endchar
	//Send that message
	transmit();
	//Wait for a response, and check if action was successful
	waitForResponseBlocking(0x81);
	//This message resets the system to lock in the above configuration changes (writing to EEPROM)
	txMessageLength=1;
	message_TX[0]=STX;
	message_TX[1]=MSB;
	message_TX[2]=LSB;
	message_TX[3]=COMADR;
	message_TX[4]=0x64;
	message_TX[5]=0x00;
	//Send that message
	transmit();
	//Wait for a response, and check if the action was successful
	waitForResponseBlocking(0x64);
	//Wait for ~3 seconds for the timer to reset
	TimerLoadSet(TIMER0_BASE,TIMER_A,30000000);
	TimerEnable(TIMER0_BASE,TIMER_A);
	while(1)
	{
		if(timeOut)
		{
			timeOut=0;
			break;
		}
	}
	RIT128x96x4Clear();
	sprintf(buffer, "System Reset!");
	RIT128x96x4StringDraw(buffer, 30, 24, 15);
	scanMode=1;
}

void UART1_Int_Handler(void)
{
    //Clear the interrupt
	unsigned long ulStatus;
	ulStatus = UARTIntStatus(RFID_BASE, true);
	UARTIntClear(RFID_BASE, ulStatus);
	if(scanMode==1)
	{
		receiveScan();
	}
	else{
	//Get the incoming byte(s), store it in the rx message array, set the new message ready flag if appropriate
		receiveResponse();
	}
}

void TIMER0A_Int_Handler(void)
{
	TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
	if(scanMode==1)
	{
		tagStatus[0]=0;//The tag that was visible is now gone
		//tagStatus[2]=The angle at which you lost it (the angle were at right now)
	}
	else
	{
		timeOut=1;
	}
}
